﻿Imports System.ComponentModel
Imports System.Collections.ObjectModel
Imports FuncClasses
Imports System.Threading.Tasks
Imports System.Threading
Imports System.Windows.Threading
Imports Microsoft.WindowsAPICodePack.Dialogs
Imports System.Reflection
Imports System.Globalization
Imports System.Xml

Public Class AddInManager
    Implements INotifyPropertyChanged

    Private _dp As Dispatcher
    Private _window As Window1
    Private _user As User

    Public Sub New(dispatcher As Dispatcher, w As Window1, user As User)
        _dp = dispatcher
        _window = w
        _user = user
        AddInList = New ObservableCollection(Of IPlugIn2)
        RegisterAddIns()
        NotifyPropertyChanged("")
    End Sub

    Public Property AddInList As ObservableCollection(Of IPlugIn2)

    Protected Sub NotifyPropertyChanged(info As [String])
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
    End Sub
    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    ''' <summary>
    ''' Checks for .AddIn files in the main directory and creates an instance of it
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub RegisterAddIns()
        For Each item In AddInList
            item.Disable()
        Next
        AddInList.Clear()

        Dim m As New Mutex
        Dim t As New Thread(Sub()
                                For Each file As String In My.Computer.FileSystem.GetFiles(System.AppDomain.CurrentDomain.BaseDirectory(), FileIO.SearchOption.SearchTopLevelOnly, "*.AddIn")
                                    Try
                                        Dim asm As Reflection.Assembly
                                        asm = Reflection.Assembly.Load(IO.File.ReadAllBytes(file))
                                        'For Each s As Type In asm.GetTypes
                                        '    Console.WriteLine(s.ToString)
                                        'Next
                                        Dim params(0) As Object
                                        params(0) = _window
                                        ' Create object and cast to interface
                                        Dim typeName As String = System.IO.Path.GetFileNameWithoutExtension(file) + ".CustomPlugIn" 'CONVENTION: INITIALIZATION NameSpace: FileName(WithoutExtension).CustomPlugIn
                                        Dim ignoreCase As Boolean = True
                                        Dim bindingAttr As BindingFlags = BindingFlags.Default
                                        Dim binder As Binder = Nothing
                                        Dim args As Object() = params
                                        Dim culture As CultureInfo = Nothing
                                        Dim activationAttributes As Object() = Nothing

                                        Dim temp As IPlugIn2 = CType(asm.CreateInstance(typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes), IPlugIn2)
                                        temp.Database = _window.Database
                                        temp.SetUser(_user)
                                        _dp.BeginInvoke(DispatcherPriority.Send, Sub()
                                                                                     m.WaitOne()
                                                                                     AddInList.Add(temp)
                                                                                     m.ReleaseMutex()
                                                                                 End Sub)
                                    Catch ex As Exception
                                        Console.WriteLine(ex.ToString)
                                        Dim result As Forms.DialogResult
                                        If TaskDialog.IsPlatformSupported Then
                                            Dim td As New TaskDialog()
                                            td.Cancelable = True
                                            td.Icon = TaskDialogStandardIcon.Information
                                            td.Caption = "Erweiterung löschen?"
                                            td.InstructionText = "Wollen Sie die Erweiterung """ + System.IO.Path.GetFileNameWithoutExtension(file) + """ löschen?"
                                            td.Text = "Anscheinend ist die Erweiterung nicht mehr kompatibel mit der verwendeten Version oder verursacht ein Problem." + vbCrLf + "Es wird nur die Erkennungsdatei gelöscht, eigene Datenbanken bleiben erhalten. Sobald eine aktualisierte Version verfügbar ist, können Sie diese unter ""Menü"" -> ""Erweiterungen"" erneut herunterladen."
                                            td.StandardButtons = TaskDialogStandardButtons.Yes Or TaskDialogStandardButtons.No
                                            If td.Show() = TaskDialogResult.Yes Then
                                                result = Forms.DialogResult.Yes
                                            Else
                                                result = Forms.DialogResult.No
                                            End If
                                        Else
                                            PSTaskDialog.cTaskDialog.ForceEmulationMode = True
                                            PSTaskDialog.cTaskDialog.EmulatedFormWidth = 450
                                            result = PSTaskDialog.cTaskDialog.MessageBox("Erweiterung löschen?", "Wollen Sie die Erweiterung """ + System.IO.Path.GetFileNameWithoutExtension(file) + """ löschen?", "Anscheinend ist die Erweiterung nicht mehr kompatibel mit der verwendeten Version oder verursacht ein Problem." + vbCrLf + "Es wird nur die Erkennungsdatei gelöscht, eigene Datenbanken bleiben erhalten. Sobald eine aktualisierte Version verfügbar ist, können Sie diese unter ""Menü"" -> ""Erweiterungen"" erneut herunterladen.", PSTaskDialog.eTaskDialogButtons.YesNo, PSTaskDialog.eSysIcons.Question)
                                        End If
                                        If result = Forms.DialogResult.Yes Then
                                            Try
                                                IO.File.Delete(file)
                                            Catch : End Try
                                        End If
                                    End Try
                                Next
                                _dp.BeginInvoke(Sub()
                                                    LoadListandInit()
                                                End Sub)
                            End Sub)
        t.SetApartmentState(ApartmentState.STA)
        t.Start()
    End Sub

    Private Sub EnableCustomAddIn(src As IPlugIn2)
        src.Disable()
    End Sub

    Private Sub DisableCustomAddIn(src As IPlugIn2)
        src.Initialize()
    End Sub

    Private Sub LoadCustomAddIn(name As String)
        For Each item In AddInList
            If item.Name = name Then
                item.Initialize()
            End If
        Next
    End Sub

#Region "XML"
    Private Sub InitializeActiveAddinList()
        Dim path As String = System.AppDomain.CurrentDomain.BaseDirectory() + "\activeaddins.xml"
        Dim sb As New Text.StringBuilder
        sb.Append(path)
        'if the file doesn't exist, create a blank xml
        If Not IO.File.Exists(path) Then
            Dim fn As New IO.StreamWriter(IO.File.Open(path, IO.FileMode.Create))
            fn.WriteLine("<?xml version=""1.0"" encoding=""utf-8""?>")
            fn.WriteLine("<list>")
            fn.WriteLine("</list>")
            fn.Close() 'all done
        End If
    End Sub

    Private Sub LoadListandInit()
        Dim xml As New XmlDocument
        InitializeActiveAddinList()
        xml.Load(System.AppDomain.CurrentDomain.BaseDirectory() + "\activeaddins.xml")
        Dim root As XmlElement = xml.DocumentElement.SelectSingleNode("/list")
        Dim nodeList As XmlNodeList = root.GetElementsByTagName("item")
        Dim list As IEnumerator = nodeList.GetEnumerator
        While list.MoveNext
            Dim item As XmlElement = list.Current
            LoadCustomAddIn(item.Attributes.GetNamedItem("name").Value.ToString)
        End While
    End Sub

    Public Sub SaveAddinList()
        Dim xml As New XmlDocument
        InitializeActiveAddinList()
        xml.Load(System.AppDomain.CurrentDomain.BaseDirectory() + "\activeaddins.xml")
        Dim root As XmlElement = xml.DocumentElement.SelectSingleNode("/list")
        root.RemoveAll()
        For Each item In AddInList
            If item.IsEnabled Then
                Dim xmlitem As XmlElement = xml.CreateElement("item")
                xmlitem.SetAttribute("name", item.Name)
                root.AppendChild(xmlitem)
            End If
        Next
        xml.Save(System.AppDomain.CurrentDomain.BaseDirectory() + "\activeaddins.xml")
    End Sub
#End Region
End Class
